/*
 * @Author: 吴世扬 18368095041@163.com
 * @Date: 2022-09-08 15:46:13
 * @LastEditors: 吴世扬 18368095041@163.com
 * @LastEditTime: 2022-11-15 17:48:51
 * @FilePath: /vuecli508-datav/src/components/ui/ol-map/mixin/index.js
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
import { tk } from '../utils/index';
import markersMixin from './markers';
import polylinesMixin from './polylines';
import polygonsMixin from './polygons';
import windsMixin from './winds';
import fitViewMixin from './fitView';
import judgePolygonWithCenterInMixin from './judgePolygonWithCenterIn';
import openInfoMixin from './openInfo';

import { get as getProjection } from 'ol/proj';
import { getWidth, getTopLeft } from 'ol/extent';
import { View, Map } from 'ol';
import TileLayer from 'ol/layer/Tile';
import ImageLayer from 'ol/layer/Image';
import { WMTS } from 'ol/source';
import WMTSTileGrid from 'ol/tilegrid/WMTS';
import RasterSource from 'ol/source/Raster';

import { toRaw } from 'vue';
import props from '../props';

export default {
    mixins: [
        markersMixin,
        polylinesMixin,
        polygonsMixin,
        windsMixin,
        fitViewMixin,
        judgePolygonWithCenterInMixin,
        openInfoMixin
    ],
    props,
    data() {
        return {
            map: null,
            view: null,
            layersOption: [],
            centerFeature: null, // 测试用中心点个标记
            curShowLayerIndex: [], // 当前展示的图层索引
            isDebug: false,
            layersData: ['vec', 'cva', 'ter', 'cta', 'img', 'cia'], // 天地图图层
            theme: 'light', // 地图风格 light dark
            eventCallbackMap: {
                click: [],
                'change:resolution': [],
                moveend: []
            }
        };
    },
    mounted() {
        this.initMap();
    },
    watch: {
        mapType: {
            handler(n) {
                this.checkLayer(n);
            }
        },
        zoom: {
            handler(n) {
                if (n) {
                    this.changeMapZoom();
                }
            },
            deep: true
        },
        location: {
            handler(n) {
                if (n) {
                    this.changeMaplocation();
                }
            },
            deep: true
        }
    },
    methods: {
        // 切换地图视野级别
        changeMapZoom() {
            if (this.view) {
                this.view.setZoom(this.zoom);
            }
        },
        // 切换定位点
        changeMaplocation() {
            if (this.view) {
                this.view.setCenter([this.location.lng, this.location.lat]);
            }
        },
        // 地图样式转换
        styleLayer(originLayer) {
            // openlayer 像素转换类，可以直接当做source使用
            const raster = new RasterSource({
                sources: [
                    // 传入图层，这里是天地图矢量图或者天地图矢量注记
                    originLayer
                ],
                // 这里设置为image类型，与官方示例不同，优化速度
                operationType: 'image',
                operation: (pixels) => {
                    const pixelsTemp = pixels[0].data;
                    for (let i = 0; i < pixelsTemp.length; i += 4) {
                        const r = pixelsTemp[i];
                        const g = pixelsTemp[i + 1];
                        const b = pixelsTemp[i + 2];
                        // 运用图像学公式，设置灰度值
                        const grey = r * 0.1 + g * 0.39 + b * 0.31;
                        // 将rgb的值替换为灰度值
                        // pixelsTemp[i] = grey;
                        // pixelsTemp[i + 1] = grey;
                        // pixelsTemp[i + 2] = grey;
                        // 基于灰色，设置为蓝色，这几个数值是我自己试出来的，可以根据需求调整
                        pixelsTemp[i] = 55 - grey;
                        pixelsTemp[i + 1] = 255 - grey;
                        pixelsTemp[i + 2] = 305 - grey;
                        // pixelsTemp[i] = 11 - grey;
                        // pixelsTemp[i + 1] = 16 - grey;
                        // pixelsTemp[i + 2] = 29 - grey;
                    }
                    // 执行颜色转换方法，注意，这里的方法需要使用lib引入进来才可以使用
                    // reverseFunc(pixels[0].data);
                    return pixels[0];
                },
                // 线程数量
                threads: 10
                // //允许operation使用外部方法
                // lib: {
                //     reverseFunc: reverseFunc,
                // },
            });
            // 创建新图层，注意，必须使用 ImageLayer
            return new ImageLayer({
                visible: false,
                source: raster
            });
        },
        // 地图初始化
        initMap() {
            // 渲染地图 https://zhuanlan.zhihu.com/p/81258050
            const projection = getProjection('EPSG:4326');
            const projectionExtent = projection.getExtent();
            const size = getWidth(projectionExtent) / 256;
            const resolutions = new Array(18);
            const matrixIds = new Array(18);
            for (let z = 1; z < 19; ++z) {
                resolutions[z] = size / 2 ** z;
                matrixIds[z] = z;
            }
            this.view = new View({
                projection,
                smoothExtentConstraint: false,
                constrainResolution: true,
                center: [this.location.lng, this.location.lat],
                zoom: this.zoom,
                maxZoom: 18,
                minZoom: 12
            });
            this.layersData.forEach((name) => {
                //         this.layersOption.push(
                //             new ImageLayer({
                //                 // http://localhost:8088/
                //                 source: new Static({
                //                     url: './static/images/map/map4000x3206.jpg',
                //                     imageExtent: this.extent // 映射到地图的范围 this.extent = [109.3727171691146, 21.41933, 109.79411365219, 21.73431]
                //                 }),
                //                 visible: false
                //             })
                //         );
                const curUrl = `http://t{0-7}.tianditu.gov.cn/${name}_c/wmts?tk=${tk}`;
                const source = new WMTS({
                    url: curUrl,
                    layer: name,
                    matrixSet: 'c',
                    format: 'tiles',
                    style: 'default',
                    projection,
                    tileGrid: new WMTSTileGrid({
                        origin: getTopLeft(projectionExtent),
                        resolutions,
                        matrixIds
                    }),
                    crossOrigin: 'Anonymous',
                    wrapX: true
                });
                let layer;
                if (this.theme === 'dark' && name === 'vec') {
                    layer = this.styleLayer(source); // 像素转换
                } else {
                    layer = new TileLayer({
                        opacity: 1,
                        source,
                        visible: false
                    });
                }
                this.layersOption.push(layer);
            });
            this.map = new Map({
                layers: toRaw(this.layersOption), // vue3递归proxy响应式对象，然后raster用到了js多线程,线程交互无法传递proxy对象会报错（处理的时候会将当前layer传过去，然后vue3递归proxy导致取到的layer也是个proxy），所以这里要转成原型取
                target: 'map',
                view: this.view
            });
            this.checkLayer(1);
            this.addEvent();
        },
        addEvent() {
            // 地图点击事件
            this.map.on('click', (e) => {
                this.eventCallbackMap['click'].forEach((fn) => {
                    fn(e);
                });
            });
            this.view.on('change:resolution', (e) => {
                this.eventCallbackMap['change:resolution'].forEach((fn) => {
                    fn(e);
                });
                const zoom = Math.ceil(this.view.getZoom());
                const center = this.view.getCenter();
                this.$emit('zoomend', {
                    zoom,
                    center: {
                        lng: center[0],
                        lat: center[1]
                    }
                });
            });

            this.map.on('moveend', (e) => {
                this.eventCallbackMap['moveend'].forEach((fn) => {
                    fn(e);
                });
            });
        },
        // 图层切换-可改写
        checkLayer(type) {
            const layers = this.map.getLayers();
            this.curShowLayerIndex.forEach((index) => {
                layers.item(index).setVisible(false);
            });
            switch (type) {
                case 1:
                    layers.item(0).setVisible(true);
                    layers.item(1).setVisible(true);
                    this.curShowLayerIndex = [0, 1];
                    break;
                case 2:
                    layers.item(4).setVisible(true);
                    layers.item(5).setVisible(true);
                    this.curShowLayerIndex = [4, 5];
                    break;
                default:
                    break;
            }
        }
    }
};
